--
-- Author: shunguo.chen
-- Date: 2018-11-09 14:27:08
--
-- TeamModel_match TeamModel 队伍匹配

local TeamVo = import(".TeamVo")
local TeamTargetVo = import(".TeamTargetVo")

local ClassRef = import(".TeamModel")

local MATH_MIN = math.min

function ClassRef:initTeamTarget()
    -- 竞速副本id
    self._speedDungeonIDs = {}
    -- 当前自动申请的目标ids（散人）
    self._curAutoApplyTargetIds = {}
    -- 目标推荐队伍page缓存
    self._curPageCache = {}
    -- 目标推荐队伍最大page缓存
    self._curPageMaxCache = {}

    -- 刷新定时器和目标id
    self._refreshCron = nil
    self._refreshTargetId = nil

    -- 解析teamTarget表
    local typeConfs = GD:queryTeamTargetTypes()
    local thirdConfs = GD:queryTeamTargets()
    local teamTargetDict = {}
    local teamTarget, typeConf
    for k,conf in pairs(thirdConfs) do
        teamTarget = TeamTargetVo.new(conf)

        typeConf = typeConfs[conf.type]
        teamTarget:setTeamMatchType(tonumber(typeConf.type))
        teamTarget:setTypeName(typeConf.name)

        teamTargetDict[tonumber(k)] = teamTarget
    end

    -- 所有TeamTarget的dict
    self._teamTargetDict = teamTargetDict

    -- 解析teamTarget_type表
    local targetsList = {}
    local targetTypeDict = {}
    local id, tp, name, target, subIds, subTarget, teamTarget, subTargets, thirdTargets
    for k,conf in pairs(typeConfs) do
        id = tonumber(k)
        tp = tonumber(conf.type)
        name = L(conf.name)

        subTargets = {}
        target = {id=id, tp=tp, name=name, subTargets=subTargets}
        targetTypeDict[id] = tp

        if self:isThreeLayerTeamTargetType(id) then
            -- 三级菜单，普通5人地下城+团队地下城
            subIds = string.splitTwice(conf.subIds, nil, true)
            for i,ids in ipairs(subIds) do
                subTarget = teamTargetDict[ids[1]]
                thirdTargets = {}
                for j,v in ipairs(ids) do
                    teamTarget = teamTargetDict[v]
                    thirdTargets[j] = teamTarget

                    -- 大目标开放等级是第一个子目标的开放等级
                    if i == 1 and j == 1 then
                        target.openLv = teamTarget:getOpenLv()
                    end
                end
                subTarget:setSubTargets(thirdTargets)
                table.insert(subTargets, subTarget)
            end
        else
            -- 二级菜单
            subIds = table.tonumber(string.split(conf.subIds, ";"))
            for i,v in ipairs(subIds) do
                teamTarget = teamTargetDict[v]
                subTargets[i] = teamTarget

                -- 大目标开放等级是第一个子目标的开放等级
                if i == 1 then
                    target.openLv = teamTarget:getOpenLv()
                end
            end
        end

        targetsList[tp] = targetsList[tp] or {}
        table.insert(targetsList[tp], target)
    end

    -- dungeon 排序
    table.sort(targetsList[Enums.TeamMatchType.Dungeon], function(a, b)
        return a.id < b.id
    end)

    -- 包含层级的所有匹配目标
    self._matchTargetsList = targetsList
    -- 目标类型-》匹配类型转化
    self._targetTypeDict = targetTypeDict

    -- dump(self._teamTargetDict, "TeamModel._teamTargetDict", 5)
    -- dump(self._matchTargetsList, "TeamModel._matchTargetsList", 5)
end

-- 目标目录类型是三层结构
function ClassRef:isThreeLayerTeamTargetType(tp)
    return tp == Enums.TeamTargetType.normal or tp == Enums.TeamTargetType.legion
end

-- 获取组队查找器几个入口各子项的开放等级
function ClassRef:getTargetTypeOpenLvDict(matchType)
    local dict = {}
    local targets = self._matchTargetsList[matchType]
    if matchType == Enums.TeamMatchType.Dungeon then
        -- 三层结构，只取第一层的开放等级
        for i,v in ipairs(targets) do
            dict[i] = v.openLv
        end
    else
        -- 二层结构，目前且只有一个一级，取第一个下面的开放等级即可
        local subTargets = targets[1].subTargets
        for i,target in ipairs(subTargets) do
            dict[target.id] = target:getOpenLv()
        end
    end

    return dict
end

function ClassRef:onEnterMap()
    self:C2S_GetSpeedDungeonIDs()
    self:C2S_GetSpeedDungeonAchievements()

    local autoJoinList = UD:getAutoJoinList()
    if #autoJoinList > 0 then
        UD:clearAutoJoinList()
        self._curAutoApplyTargetIds = autoJoinList
        for i,id in ipairs(autoJoinList) do
            local teamTarget = self._teamTargetDict[id]
            teamTarget:setAutoApply(true)
        end
    end

    -- 设置副本次数
    local dungeonSubId, dungeonTimes
    for k,teamTarget in pairs(self._teamTargetDict) do
        dungeonSubId = teamTarget:getDungeonSubId()
        if dungeonSubId then
            dungeonTimes = UD:getDungeonTimes(dungeonSubId)
            if dungeonTimes then
                teamTarget:setDungeonTimes(dungeonTimes)
            end
        end
    end
end

function ClassRef:onDailyUpdate(isWeekChange)
    self:C2S_GetSpeedDungeonIDs()
    self:C2S_GetSpeedDungeonAchievements()

    for k,teamTarget in pairs(self._teamTargetDict) do
        teamTarget:onDailyUpdate(isWeekChange)
    end
end

-- 副本次数有更新，修改玩法目标的副本次数
function ClassRef:onUpdateDungeonTimes(dungeonSubId, dungeonTimes)
    for k,teamTarget in pairs(self._teamTargetDict) do
        if teamTarget:getDungeonSubId() == dungeonSubId then
            teamTarget:setDungeonTimes(dungeonTimes)
        end
    end
end

-- 清除page缓存
function ClassRef:clearPageCache()
    self._curPageCache = {}
    self._curPageMaxCache = {}
end 

-- 通过id获得队伍目标
function ClassRef:getTeamTargetById(id)
    if not id then return end
    local teamTarget = self._teamTargetDict[id]
    if teamTarget then
        local isOpen = self:isTeamTargetOpen(id)
        teamTarget:setIsOpen(isOpen)
        return teamTarget
    end
end

-- 获得所有"活动副本"的目标
function ClassRef:getActivityTeamTargets()
    local targets = {}
    for k, v in ipairs(Enums.IndexForActivityId) do
        local teamTarget = self._teamTargetDict[v]
        teamTarget:setIsOpen(self:isTeamTargetOpen(v))
        table.insert(targets, teamTarget)
    end
    return targets
end

-- 解析组队查找器打开的参数
-- data = {
--     targetId = ,     --Enums.TeamTarget 
--     matchType = ,     --Enums.TeamMatchType
--     targetType = ,     --Enums.TeamTargetType
-- }
-- 传入类型1 nil 全部使用默认值
-- 传入类型2 targetId 可以解析出matchType和targetType
-- 传入类型3 matchType+targetType 指定查找类型和目标类型，使用默认targetId
-- 传入类型4 matchType 指定查找类型，使用默认targetType targetId
-- 传入类型5 targetType 指定目标类型，可以解析出matchType，使用默认targetId
-- 特殊逻辑：五人小队／团队副本/竞速副本（限时开启） 全可见
function ClassRef:checkTeamMatchOpenParams(params)
    local targetId, matchType, targetType
    local isOpen = false
    local reason
    if params then
        targetId = params.targetId
        matchType = params.matchType
        targetType = params.targetType
    end
    if targetId then
        local teamTarget = self._teamTargetDict[targetId]
        if not teamTarget then
            --活动未开启时候，连配置都没有，肯定未开放
            isOpen = false
        else
            matchType = teamTarget:getTeamMatchType()
            if teamTarget:isNormal() or teamTarget:isLegion() then
                isOpen = true
            else
                isOpen, reason = self:isTeamTargetOpen(targetId, true)
            end
        end
    else
        if not matchType then
            if targetType then
                matchType = self._targetTypeDict[targetType]
            else
                matchType = Enums.TeamMatchType.Dungeon
            end
        end

        local targets = self._matchTargetsList[matchType]
        if not targetType then
            targetType = targets[1].id
        end
        
        for _,target in ipairs(targets) do
            if target.id == targetType then
                local subTargets
                if self:isThreeLayerTeamTargetType(targetType) then
                    -- 普通五人地下城+团队副本，三层结构，默认用最后解锁的targetId
                    subTargets = target.subTargets
                    local secendTarget, secondSubTargets, thirdTarget
                    for i=#subTargets,1,-1 do
                        secendTarget = subTargets[i]
                        secondSubTargets = secendTarget.subTargets
                        thirdTarget = secondSubTargets[1]

                        targetId = thirdTarget.id
                        
                        isOpen = self:isTeamTargetOpen(thirdTarget.id)
                        if isOpen then break end
                    end

                    if not isOpen then
                        isOpen = true
                    end
                elseif targetType == Enums.TeamTargetType.speed then
                    -- 竞速副本（限时开启） 全可见
                    subTargets = target.subTargets
                    for _,subTarget in ipairs(subTargets) do
                        if table.hasvalue(self._speedDungeonIDs, subTarget.id) then
                            targetId = subTarget.id
                        end
                    end
                    if not isOpen then
                        isOpen = true
                    end
                else
                    -- 其他 二层结构 找到第一个开放的targetId
                    subTargets = target.subTargets
                    for _,subTarget in ipairs(subTargets) do
                        if not reason then
                            -- 副本应该是依次开放的，原因只取第一个（最小原因）
                            isOpen, reason = self:isTeamTargetOpen(subTarget.id, true)
                        else
                            isOpen = self:isTeamTargetOpen(subTarget.id)
                        end
                        if isOpen then
                            targetId = subTarget.id
                            break
                        end
                    end
                end
                if targetId then break end
            end
        end
    end

    if isOpen then
        return true, matchType, targetId
    else
        return false, reason
    end
end

-- 获取组队查找器不同matchType开放情况，通过轮询下面的所有子目标，有任何一个开放就算开放
-- 特殊逻辑：五人小队／团队副本 全可见
function ClassRef:getMatchTypeOpenParams()
    local openParams = {false, false, false, false}
    local secondTargets, thirdTargets, isOpen
    for i,matchTargets in ipairs(self._matchTargetsList) do
        isOpen = false
        for _,firstTarget in ipairs(matchTargets) do
            secondTargets = firstTarget.subTargets
            if self:isThreeLayerTeamTargetType(firstTarget.id) then
                isOpen = true
                -- 三级结构
                -- for _, secondTarget in ipairs(secondTargets) do
                --     thirdTargets = secondTarget.subTargets
                --     for _, thirdTarget in ipairs(thirdTargets) do
                --         isOpen = self:isTeamTargetOpen(thirdTarget.id)
                --         if isOpen then break end
                --     end
                --     if isOpen then break end
                -- end
            else
                -- 二级结构
                for _, secondTarget in ipairs(secondTargets) do
                    isOpen = self:isTeamTargetOpen(secondTarget.id)
                    if isOpen then break end
                end
            end

            if isOpen then break end
        end

        openParams[i] = isOpen
    end

    -- 完美版不要2，3类型
    if app:isInnerPwrd() then
        openParams[2] = false
        openParams[3] = false
    end

    return openParams
end

-- 组队目标是否开启
function ClassRef:isTeamTargetOpen(teamTargetId, withReason)
    if not teamTargetId then
        if withReason then
            return false, L("lua_code_text_182")
        else
            return false
        end
    end

    local teamTarget = self._teamTargetDict[teamTargetId]
    if not teamTarget then
        release_print("TeamModel.isTeamTargetOpen don't have targetId", teamTargetId)
        if withReason then
            return false, L("lua_code_text_182")
        else
            return false
        end
    end

    local isOpen, reason = teamTarget:isConfOpen(withReason)
    if isOpen then
        if teamTarget.type == Enums.TeamTargetType.speed then
            -- 限速副本限时开启
            isOpen = table.hasvalue(self._speedDungeonIDs, teamTarget.id)
        elseif teamTarget.type == Enums.TeamTargetType.secret then
            -- 秘境当前只能在某一层
            isOpen = SecretManager:isTeamTargetOpen(teamTarget)
        elseif teamTarget.id == Enums.TeamTarget.dynastyBattle or
            teamTarget.id == Enums.TeamTarget.storyTask then
            -- 公会战和剧情副本不显示匹配
            isOpen = false
            reason = L("lua_code_text_182")
        end
    end
    return isOpen, reason
end

-- matchType = Enums.TeamMatchType
function ClassRef:getMatchTargets(matchType, targetId)
    local targets = self._matchTargetsList[matchType]
    local openTargets = {}

    local defaultTargetId
    local secondTargets, thirdTargets, curSecondTargets, curThirdTargets

    -- 五人小队／团队副本/竞速副本(限时开启) 全可见，其他逐级查看是否开启，并且过滤掉下级开启个数为0的目标
    for i, firstTarget in ipairs(targets) do
        secondTargets = firstTarget.subTargets
        curSecondTargets = {}
        if self:isThreeLayerTeamTargetType(firstTarget.id) then
            -- 三级结构
            for j, secondTarget in ipairs(secondTargets) do
                thirdTargets = secondTarget.subTargets
                curThirdTargets = {}
                for k, thirdTarget in ipairs(thirdTargets) do
                    table.insert(curThirdTargets, thirdTarget)
                    if self:isTeamTargetOpen(thirdTarget.id) then
                        thirdTarget:setIsOpen(true)
                    else
                        thirdTarget:setIsOpen(false)
                    end
                end
                secondTarget:setCurSubTargets(curThirdTargets)
                if #curThirdTargets > 0 then
                    table.insert(curSecondTargets, secondTarget)

                    -- 如果没有指定targetId，默认用最后解锁的普通本targetId
                    if i == 1 and not targetId then
                        if curThirdTargets[1]:isOpen() then
                            defaultTargetId = curThirdTargets[1].id
                        end
                    end
                end
            end
        elseif firstTarget.id == Enums.TeamTargetType.speed then
            -- 竞速副本（限时开启）也可见
            for j, secondTarget in ipairs(secondTargets) do
                if table.hasvalue(self._speedDungeonIDs, secondTarget.id) then
                    table.insert(curSecondTargets, secondTarget)
                end
                secondTarget:setIsOpen(self:isTeamTargetOpen(secondTarget.id))
            end

            if i == 1 and not targetId and #curSecondTargets > 0 then
                defaultTargetId = curSecondTargets[1].id
            end
        else
            -- 二级结构
            for j, secondTarget in ipairs(secondTargets) do
                if self:isTeamTargetOpen(secondTarget.id) then
                    table.insert(curSecondTargets, secondTarget)
                    secondTarget:setIsOpen(true)
                else
                    secondTarget:setIsOpen(false)
                end
            end

            if i == 1 and not targetId and #curSecondTargets > 0 then
                defaultTargetId = curSecondTargets[1].id
            end
        end

        firstTarget.curSubTargets = curSecondTargets
        if #curSecondTargets > 0 then
            table.insert(openTargets, firstTarget)
        end
    end

    if defaultTargetId then
        targetId = defaultTargetId
    end

    -- 是否要显示未开放的目标
    local idxs
    for i,firstTarget in ipairs(openTargets) do
        curSecondTargets = firstTarget.curSubTargets
        if self:isThreeLayerTeamTargetType(firstTarget.id) then
            for j,secondTarget in ipairs(curSecondTargets) do
                curThirdTargets = secondTarget.curSubTargets
                for k,thirdTarget in ipairs(curThirdTargets) do
                    if targetId == thirdTarget.id then
                        idxs = {i,j,k}
                        break
                    end
                end
                if idxs ~= nil then break end
            end
        else
            for j,secondTarget in ipairs(curSecondTargets) do
                if targetId == secondTarget.id then
                    idxs = {i,j}
                    break
                end
            end
        end
        if idxs ~= nil then break end
    end

    if not idxs then
        if matchType == Enums.TeamMatchType.Dungeon then
            idxs = {1,1,1}
        else
            idxs = {1,1}
        end
    end

    -- print("TeamModel.getMatchTargets", matchType, targetId)
    -- dump(openTargets, "TeamModel.getMatchTargets", 5)
    -- dump(idxs, "TeamModel.idxs", 5)
    return openTargets, idxs
end

------------------------- 竞速副本 start ---------------------
function ClassRef:getCurSpeedDungeonIDs()
    return self._speedDungeonIDs
end

function ClassRef:C2S_GetSpeedDungeonIDs()
    app.session:request("pb_speeddungeon.C2S_GetSpeedDungeonIDs", {}, function(msg)
        -- dump(msg, "C2S_GetSpeedDungeonIDs")
        local ids = {}
        for i,v in ipairs(msg.ids) do
            ids[i] = v
        end
        self._speedDungeonIDs = ids
    end)
end

-- 获得竞速副本通关信息
function ClassRef:C2S_GetSpeedDungeonAchievements()
    app.session:request("pb_speeddungeon.C2S_GetSpeedDungeonAchievements", {target=-1}, function(msg)
        -- dump(msg, "C2S_GetSpeedDungeonAchievements")
        if msg.OK then
            for i,v in ipairs(msg.achievements) do
                local teamTarget = self._teamTargetDict[v.target]
                teamTarget:updateSpeedInfo(v)
            end
        end
    end)
end

-- 竞速副本结果
function ClassRef:S2C_SpeedDungeonResult(msg)
    -- dump(msg, "S2C_SpeedDungeonResult")
    if msg.isSuccess then
        -- 先展示界面，再刷新数据，界面显示需要根据数据前后变化
        app:sendMsg("TeamMatchController", "openSpeedDungeonWinView", msg)

        -- 根据竞速副本结果更新竞速副本信息，避免频繁拉取
        local teamTarget = self._teamTargetDict[msg.target]
        local speedInfo = teamTarget:getSpeedInfo()
        speedInfo:updateRecord(msg.finishSeconds)
        if msg.newRecord then
            speedInfo:updateReward(msg.newRewardList)
        end
    else
        UIHandler:handleMessage({id = Constant.FUNC_TYPE_BATTLE_FAILED,mode = "open"})
    end
end

------------------------- 竞速副本 end ---------------------

------------------------- 队伍更新 start ---------------------
function ClassRef:S2C_TeamInfoUpdate(msg)
    -- dump(msg, "S2C_TeamInfoUpdate", 3)
    if not msg.isCrossTeam then
        -- 跨服副本中，跨服队伍，屏蔽掉正常队伍的信息
        if self:_isCrossDungeon() then
            print("isCrossDungeon ignore normal S2C_TeamInfoUpdate")
            return
        end
    end

    local hasTeamBefore = self:hasTeam()
    self:setTeam(msg.teamInfo, msg.isCrossTeam)

    -- 之前没有队伍，现在有队伍，发送加入队伍消息
    if not hasTeamBefore and self:hasTeam() then
        EM:notify("onJoinTeam")
    end

--    local myUid = UD:getUid()
    -- 自动设置自动跟随，1.有队伍 2.我不是跟随状态 3.我不是队长 4.我设置了自动跟随
--    if self:hasTeam() and
--        not self._team:isWithTeam(myUid) and
--        not self._team:isLeader(myUid) then
--        self:getAlwaysWithTeam() then     --临时删掉客户端自动跟随
--        self:reqFollowLeader(true)
--    end

    local changeType = protobuf.enum_id("pb_team.TeamInfo_ChangeType", msg.type)
    if 0 == changeType then -- 正常更新
    elseif 1 == changeType then -- 成员改变
        EM:notify("onTeamMemberUpdate")
        app:dispatchCustomEvent("EVENT_TEAM_UPDATE")
    elseif 2 == changeType then -- 设置改变
        EM:notify("onTeamSettingUpdate")
    elseif 3 == changeType then -- 被踢出队伍
        display.pushToast( L("lua_code_text_208") )
        UIHandler:hideHeadMenu() -- 清除对其他玩家的操作菜单
    elseif 4 == changeType then -- 队长改变
        local str = string.format( L("lua_code_text_323"), self._team:getLeaderName() )
        display.pushToast( str )

        EM:notify("onTeamLeaderChanged")
    elseif 5 == changeType then -- 战备状态发生改变
    end

    -- 根据 我 是否是跟随状态，更新npc头顶交互功能
    NpcManager:updateNpcVisibilityByWithTeam( self:isWithTeam() )
end

function ClassRef:checkDungeonMatch()
    if not self._dungeonMatchMsg then return end
    local msg = self._dungeonMatchMsg
    self._dungeonMatchMsg = nil
    
    if msg.AddStamp > 0 and msg.ID > 0 then
        local serverTime = app.session:getServerTime()
        local curTime = math.ceil(serverTime - msg.AddStamp)
        if curTime < 30 then
            app:sendMsg("NewTeamReadyAndSettingController", "openDungeonMatchView", msg.ID, curTime)
        end
    end
end

-- 副本匹配开始
function ClassRef:S2C_RecoverDungeonMatch(msg)
    -- dump(msg, "S2C_RecoverDungeonMatch")
    self._dungeonMatchMsg = msg

    if MapManager:isEnterGame() then
        self:checkDungeonMatch()
    end
end
-- 副本匹配开始
function ClassRef:S2C_StartTeamTargetMatchNotify(msg)
    -- dump(msg, "S2C_StartTeamTargetMatchNotify")
    EM:notify("onDisplayIndicator", false)
    app:sendMsg("NewTeamReadyAndSettingController", "openDungeonMatchView", msg.TargetId)
end
-- 副本匹配结束
function ClassRef:S2C_FinishTeamTargetMatchNotify(msg)
    -- dump(msg, "S2C_FinishTeamTargetMatchNotify")
    app:sendMsg("NewTeamReadyAndSettingController", "closeDungeknMatchView")
    if msg.TargetId > 0 then
        -- 匹配成功 由服务器发起进入副本
        app:sendMsg("NewTeamReadyAndSettingController", "outDungeons")

        -- local teamTarget = self._teamTargetDict[msg.TargetId]
        -- app:sendMsg("NewTeamReadyAndSettingController", "teamReadyStart", teamTarget)
    end
end
------------------------- 队伍更新 end ---------------------


------------------------- 队伍操作 start ---------------------
-- 散人自动申请加入目标的队伍
-- teamTarget TeamTargetVo
function ClassRef:C2S_PlayerAutoJoin(teamTarget, isAutoJoin)
    if self:isInCrossMatch() then
        display.pushToast(L("CrossServerTips23"))
        app:sendMsg("TeamMatchController", "updateAutoApply", teamTarget)
        app:sendMsg("PvpEliteController", "updateAutoApply", teamTarget)
        app:sendMsg("PvpChallengeController", "updateAutoApply", teamTarget)
        return
    end

    local teamTargetId = teamTarget.id
    local params = {teamTarget=teamTargetId, autoJoin=isAutoJoin}
    -- dump(params, "C2S_PlayerAutoJoin")
    app.session:request("pb_team.C2S_PlayerAutoJoin", params, function(msg)
        -- dump(msg, "C2S_PlayerAutoJoin")
        if msg.OK then
            teamTarget:setAutoApply(isAutoJoin)
            if isAutoJoin then
                table.insert(self._curAutoApplyTargetIds, teamTargetId)
            else
                table.removebyvalue(self._curAutoApplyTargetIds, teamTargetId)
            end

            app:sendMsg("TeamMatchController", "updateAutoApply", teamTarget)
            app:sendMsg("PvpEliteController", "updateAutoApply", teamTarget)
            app:sendMsg("PvpChallengeController", "updateAutoApply", teamTarget)
        end
    end)
end

-- 更新招募信息
function ClassRef:C2S_UpdateRecruitInfo(recruitInfo)
    -- dump(recruitInfo, "C2S_UpdateRecruitInfo")

    -- 如果满足下列要求，需要主动把队伍切换成团队模式 1.是自动招募 2.目标不为空 3.不是团队 4.是团队玩法
    if TEAM_LEGION_ENABLE and recruitInfo.autoRecruit and recruitInfo.targetID > 0 and not self._team:isLegion() then
        local teamTarget = self._teamTargetDict[recruitInfo.targetID]
        if teamTarget:isLegion() then
            self:reqUpdateTeamGrade(1)
        end
    end

    app.session:request("pb_team.C2S_UpdateRecruitInfo", {recruitInfo=recruitInfo}, function(msg)
        -- dump(msg, "C2S_UpdateRecruitInfo recv")
    end)
end

-- 请求副本匹配
function ClassRef:C2S_StartTeamTargetMatch(targetId)
    -- print("C2S_StartTeamTargetMatch", targetId)
    EM:notify("onDisplayIndicator", true)

    app.session:request("pb_team.C2S_StartTeamTargetMatch", 
        {TargetId=targetId}, 
        function(msg)
        -- dump(msg, "C2S_StartTeamTargetMatch recv")
        end, 
        nil,
        function(errMsg)
            EM:notify("onDisplayIndicator", false)
            app:sendMsg("NewTeamReadyAndSettingController", "closeDungeknMatchView")
        end)
end
-- 取消副本匹配
function ClassRef:C2S_CancelTeamTargetMatch()
    app.session:request("pb_team.C2S_CancelTeamTargetMatch", {}, function(msg)
        -- dump(msg, "C2S_CancelTeamTargetMatch recv")
    end)
end

-- 拉取推荐队伍
-- isManual 手动刷新需要累加pageIdx
function ClassRef:C2S_GetTeamList(targetId, isManual)
    if self._refreshCron then
        scheduler.cancelCron(self._refreshCron)
        self._refreshCron = nil
        self._refreshTargetId = nil
    end

    local pageIdx = 1
    if isManual then
        if self._curPageCache[targetId] then
            pageIdx = self._curPageCache[targetId] + 1
        end

        local maxIdx = self._curPageMaxCache[targetId] or 1
        if pageIdx > maxIdx then
            pageIdx = 1
        end
        self._curPageCache[targetId] = pageIdx
    end

    -- print("TeamModel.C2S_GetTeamList", targetId, pageIdx)

    app.session:request("pb_team.C2S_GetTeamList", {targetID=targetId, pageIndex=pageIdx}, 
        function(msg)
            -- dump(msg, "C2S_GetTeamList msg")

            self._curPageMaxCache[targetId] = msg.maxIndex

            local teamTarget = self._teamTargetDict[targetId]
            local maxNum = teamTarget:getMaxNum()
            local isCanJoinAnyStatus = teamTarget:isCanJoinAnyStatus()
            local teams = {}
            local fullTeams = {}
            local team, memberLen, leader
            for i,v in ipairs(msg.teams) do
                team = TeamVo.new(v)
                team:setTeamTargetVo(teamTarget, false)

                memberLen = #v.teamMembers + #v.robots
                if memberLen < maxNum then
                    leader = team:getLeader()
                    if leader and not leader:isOffLeave() then
                        -- 不是很明确需求 正常队伍、战斗中队伍
                        if team:isTeamNormal() or team:isTeamBattle() then
                            table.insert( teams, team )
                        elseif team:isTeamBusy() and isCanJoinAnyStatus then
                            table.insert( teams, team )
                        end
                    end
                else
                    -- 满员的队伍也显示出来，排在最后
                    table.insert(fullTeams, team)
                end
            end

            -- 1.最低等级升序 2.队伍战力降序 3.队伍人数降序 4.队长uid升序
            table.sort(teams, function(a, b)
                local aMinLv = a.recruitInfo.minLevel
                local bMinLv = b.recruitInfo.minLevel
                if aMinLv == bMinLv then
                    local aCapacity = a:getTeamTotalCapacity()
                    local bCapacity = b:getTeamTotalCapacity()
                    if aCapacity == bCapacity then -- 队伍总战力相同？
                        local aNum = a:getMemberNum()
                        local bNum = b:getMemberNum()
                        if aNum == bNum then -- 队伍成员人数相同？
                            return a:getLeaderUid() < b:getLeaderUid()
                        else
                            return aNum > bNum
                        end
                    else
                        return aCapacity > bCapacity
                    end
                else
                    return aMinLv < bMinLv
                end
            end)

            teams = table.attach(teams, fullTeams)
            app:sendMsg("TeamMatchController", "refreshTeamList", teams)
            app:sendMsg("PvpChallengeController", "refreshTeamList", teams)
            EM:notify(ViewEvent.CSElite_TeamListUpdate, teams)
            
            -- 如果一个队伍也没有，5秒种之后且目标未变再拉取一次
            if #teams == 0 then
                self._refreshTargetId = targetId
                self._refreshCron = scheduler.newCron(function()
                    self._refreshCron = nil
                    local curTargetId = app:sendMsg("TeamMatchController", "getCurTeamTargetId")
                    if self._refreshTargetId and self._refreshTargetId == curTargetId then
                        self:C2S_GetTeamList(self._refreshTargetId, true)
                    end
                    self._refreshTargetId = nil
                end, 5)
            end

        end)
end
------------------------- 队伍操作 end ---------------------

return ClassRef